package com.eastfair.imaster.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.core.snowflake.DefaultUidGenerator;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.core.utils.StringUtils;
import com.eastfair.imaster.dao.ShopWindowMapper;
import com.eastfair.imaster.dto.ShopWindowDTO;
import com.eastfair.imaster.entity.ShopWindow;
import com.eastfair.imaster.entity.ShopWindowPoint;
import com.eastfair.imaster.mydao.MyShopWindowMapper;
import com.eastfair.imaster.service.ExhibitorService;
import com.eastfair.imaster.service.ShopWindowPointService;
import com.eastfair.imaster.service.ShopWindowService;
import com.eastfair.imaster.vo.ShopWindowPointVO;
import com.eastfair.imaster.vo.ShopWindowVO;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 业务实现类
 * 电子橱窗表
 * </p>
 *
 * @author zjn
 * @date 2022-03-15
 */
@Slf4j
@Service
@DS("#thread.tenant")
public class ShopWindowServiceImpl extends SuperServiceImpl<ShopWindowMapper, ShopWindow> implements ShopWindowService {

    @Autowired
    private ShopWindowPointService shopWindowPointService;
    @Autowired
    private MyShopWindowMapper myShopWindowMapper;

    @Override
    protected R<Boolean> handlerSave(ShopWindow model) {
        model.setId(DefaultUidGenerator.getUidOfProjectId(ContextUtil.getProjectId()));
        model.setProjectId(ContextUtil.getProjectId());
        model.setExhibitionId(ContextUtil.getExhibitionId());
        return R.successDef();
    }

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ShopWindow> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    @Override
    @GlobalTransactional(name = "saveShopWindow", rollbackFor = Exception.class)
    public R<Boolean> saveShopWindow(ShopWindowDTO shopWindowDTO) {
        if (Objects.isNull(shopWindowDTO) || StringUtils.isBlank(shopWindowDTO.getUrl())
                || Objects.isNull(shopWindowDTO.getExhibitorId())) {
            return R.fail(ExceptionCode.ERROR_NULL_PARAMS);
        }
        ShopWindow shopWindow = BeanUtil.toBean(shopWindowDTO, ShopWindow.class);
        save(shopWindow);

        return saveShopWindowPoint(shopWindowDTO, shopWindow.getId());
    }

    @Override
    @GlobalTransactional(name = "deleteShopWindow", rollbackFor = Exception.class)
    public R<Boolean> deleteShopWindow(Long id) {
        if (Objects.isNull(id)) {
            return R.fail(ExceptionCode.ERROR_NULL_ID);
        }

        ShopWindow shopWindow = ShopWindow.builder().id(id).isDeleted(BusinessConstant.DELETE_YES).build();
        updateById(shopWindow);

        // 删除点位信息
        return shopWindowPointService.deleteByShopWindowId(id);
    }

    @Override
    @GlobalTransactional(name = "updateShopWindow", rollbackFor = Exception.class)
    public R<Boolean> updateShopWindow(ShopWindowDTO shopWindowDTO) {
        if (Objects.isNull(shopWindowDTO) || Objects.isNull(shopWindowDTO.getId())) {
            return R.fail(ExceptionCode.ERROR_NULL_ID);
        }
        ShopWindow shopWindow = BeanUtil.toBean(shopWindowDTO, ShopWindow.class);
        updateById(shopWindow);

        // 删除点位信息
        shopWindowPointService.deleteByShopWindowId(shopWindow.getId());

        return saveShopWindowPoint(shopWindowDTO, shopWindowDTO.getId());
    }

    private R<Boolean> saveShopWindowPoint(ShopWindowDTO shopWindowDTO, Long shopWindowId) {
        if (CollectionUtil.isEmpty(shopWindowDTO.getShopWindowPointDTOList())) {
            return R.success(true);
        }
        Long exhibitorId;
        if (Objects.nonNull(shopWindowDTO.getExhibitorId())) {
            exhibitorId = shopWindowDTO.getExhibitorId();
        } else {
            exhibitorId = getById(shopWindowDTO.getId()).getExhibitorId();
        }

        List<ShopWindowPoint> shopWindowPointList = ConvertUtil.convertList(shopWindowDTO.getShopWindowPointDTOList(), ShopWindowPoint.class);
        shopWindowPointList.forEach(shopWindowPoint -> {
            shopWindowPoint.setId(DefaultUidGenerator.getUidOfProjectId(ContextUtil.getProjectId()));
            shopWindowPoint.setProjectId(ContextUtil.getProjectId());
            shopWindowPoint.setExhibitionId(ContextUtil.getExhibitionId());
            shopWindowPoint.setExhibitorId(exhibitorId);
            shopWindowPoint.setShopWindowId(shopWindowId);
        });
        return R.success(shopWindowPointService.saveBatch(shopWindowPointList));
    }

    @Override
    public R<ShopWindowVO> getShopWindowById(Long id) {
        if (Objects.isNull(id)) {
            return R.fail(ExceptionCode.ERROR_NULL_ID);
        }
        ShopWindow shopWindow = getById(id);
        if (Objects.isNull(shopWindow)) {
            return null;
        }
        ShopWindowVO shopWindowVO = BeanUtil.toBean(shopWindow, ShopWindowVO.class);
        // 获取点位信息
        return R.success(assembleShopWindowPoint(Arrays.asList(shopWindowVO)).get(0));
    }

    @Override
    public R<Page<ShopWindowVO>> pageShopWindow(PageParams<ShopWindowDTO> params) {
        Long exhibitionId = Objects.nonNull(params.getModel().getExhibitionId()) ? params.getModel().getExhibitionId() : ContextUtil.getExhibitionId();
        //忽略默认排序规则
        Page<ShopWindowDTO> shopWindowPagParams = params.buildPage();
        shopWindowPagParams.setOrders(Collections.EMPTY_LIST);
        Page<ShopWindowVO> shopWindowVOList = myShopWindowMapper.pageList(shopWindowPagParams, params.getModel(), ContextUtil.getProjectId(), exhibitionId);
        Page<ShopWindowVO> shopWindowVOPage = ConvertUtil.convertPage(shopWindowVOList, ShopWindowVO.class);
        assembleShopWindowPoint(shopWindowVOPage.getRecords());
        return R.success(shopWindowVOPage);
    }

    @Override
    public R<Boolean> simpleUpdate(ShopWindowDTO shopWindowDTO) {
        if (Objects.isNull(shopWindowDTO) || Objects.isNull(shopWindowDTO.getId())) {
            return R.fail(ExceptionCode.ERROR_NULL_PARAMS);
        }
        ShopWindow shopWindow = getById(shopWindowDTO.getId());
        if (Objects.isNull(shopWindow)) {
            return R.fail(ExceptionCode.ERROR_NULL_ID);
        }
        if (Objects.nonNull(shopWindowDTO.getRecommend())
                && shopWindowDTO.getRecommend() == BusinessConstant.YES
                && shopWindow.getRecommend() == BusinessConstant.NO) {
            shopWindowDTO.setRecommendTime(LocalDateTime.now());
        }

        return R.success(updateById(BeanUtil.toBean(shopWindowDTO, ShopWindow.class)));
    }

    @Override
    public R<List<ShopWindowVO>> listRecommend() {
        ShopWindowDTO shopWindowDTO = new ShopWindowDTO();
        shopWindowDTO.setRecommend(BusinessConstant.YES);
        shopWindowDTO.setIsEnabled(BusinessConstant.ENABLE_YES);
        List<ShopWindowVO> shopWindowVOList = myShopWindowMapper.list(shopWindowDTO, ContextUtil.getProjectId(), ContextUtil.getExhibitionId());
        return R.success(assembleShopWindowPoint(ConvertUtil.convertList(shopWindowVOList, ShopWindowVO.class)));
    }

    /**
     * 组装橱窗点位
     *
     * @param shopWindowVOList 橱窗列表
     * @return 橱窗列表
     */
    private List<ShopWindowVO> assembleShopWindowPoint(List<ShopWindowVO> shopWindowVOList) {
        if (CollectionUtil.isNotEmpty(shopWindowVOList)) {
            shopWindowVOList.parallelStream().forEach(ShopWindowVO -> {
                R<List<ShopWindowPointVO>> shopWindowPointList = shopWindowPointService.getByShopWindowId(ShopWindowVO.getId());
                if (shopWindowPointList.getIsSuccess()) {
                    ShopWindowVO.setShopWindowPointVOList(shopWindowPointList.getData());
                }
            });
        }
        return shopWindowVOList;
    }
}
